#ifndef	SSD1306_H_
#define	SSD1306_H_

/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

/*Header File*/
#include "..\common\errcode.h"
#include "..\common\osdata.h"

/*Configurations*/
#define SPI_SENDRCV_DIS_W_SETTING   0 //The SPI PDC is temporarily disabled while configuring to send / receive
 
/*Definitions*/
#define SPI_MIN_DIVIDER 2

/*IO Ports definition*/
/* SPI0 */
/*CS0 only in PA12*/
#define SPI0_IO_CS0A  (unsigned int) AT91C_PA12_NPCS0
#define SPI0_IO_CS0B  0
/*CS1 in PA31 or in PA9*/
#if SELECT_SPI0_IO_CS1 == PA31
#define SPI0_IO_CS1A (unsigned int) AT91C_PA4_NPCS1
#define SPI0_IO_CS1B 0
#else
#define SPI0_IO_CS1A 0
#define SPI0_IO_CS1B (unsigned int) AT91C_PA9_NPCS1
#endif
/*CS2 in PA30 or in PA10*/
#if SELECT_SPI0_IO_CS2 == PA30
#define SPI0_IO_CS2A 0
#define SPI0_IO_CS2B (unsigned int) AT91C_PA30_NPCS2
#else
#define SPI0_IO_CS2A 0
#define SPI0_IO_CS2B (unsigned int) AT91C_PA10_NPCS2
#endif
/*CS3 in PA3, PA5 or PA22*/
#if SELECT_SPI0_IO_CS2 == PA3
#define SPI0_IO_CS3A 0
#define SPI0_IO_CS3B (unsigned int) AT91C_PA3_NPCS3
#elif SELECT_SPI0_IO_CS2 == PA5
#define SPI0_IO_CS3A 0
#define SPI0_IO_CS3B (unsigned int) AT91C_PA5_NPCS3
#else
#define SPI0_IO_CS3A 0
#define SPI0_IO_CS3B (unsigned int) AT91C_PA22_NPCS3
#endif

/* SPI1 */
/*CS0 only in PA12*/
#define SPI1_IO_CS0A  (unsigned int) AT91C_PA21_NPCS0
#define SPI1_IO_CS0B  0
/*CS1 in PA31 or in PA9*/
#if SELECT_SPI1_IO_CS1 == PA31
#define SPI1_IO_CS1A (unsigned int) AT91C_PA4_NPCS1
#define SPI1_IO_CS1B 0
#else
#define SPI1_IO_CS1A 0
#define SPI1_IO_CS1B (unsigned int) AT91C_PA9_NPCS1
#endif
/*CS2 in PA30 or in PA10*/
#if SELECT_SPI1_IO_CS2 == PA30
#define SPI1_IO_CS2A 0
#define SPI1_IO_CS2B (unsigned int) AT91C_PA30_NPCS2
#else
#define SPI1_IO_CS2A 0
#define SPI1_IO_CS2B (unsigned int) AT91C_PA10_NPCS2
#endif
/*CS3 in PA3, PA5 or PA22*/
#if SELECT_SPI1_IO_CS2 == PA3
#define SPI1_IO_CS3A 0
#define SPI1_IO_CS3B (unsigned int) AT91C_PA3_NPCS3
#elif SELECT_SPI1_IO_CS2 == PA5
#define SPI1_IO_CS3A 0
#define SPI1_IO_CS3B (unsigned int) AT91C_PA5_NPCS3
#else
#define SPI1_IO_CS3A 0
#define SPI1_IO_CS3B (unsigned int) AT91C_PA22_NPCS3
#endif

/*enumerations*/
//Error codes for SPI initialization
typedef enum
{
	spiInitSuccess = 0,
	spiInitMaxCs
} eSpiInitError;
 
typedef enum
{
	ChipSelect0 = 0,
	ChipSelect1 = 1,
	ChipSelect2 = 2,
	ChipSelect3 = 3,
	ChipSelectMax
} eCSDevice;

/*Types Definition, unions*/
/*#pragma anon_unions*/

typedef struct
{
	eCSDevice device;
	struct {unsigned portCHAR holdCS:1, :7; };
	unsigned portCHAR clockDivider;
	unsigned portSHORT sizeR;
	unsigned portSHORT sizeW;
	unsigned portCHAR *dataR;
	const unsigned portCHAR *dataW;
	portTickType xBlockTime;
} tSpiRWdata, *pSpiRWdata;
 
typedef struct
{
	struct {unsigned portCHAR dev_1_Enabled:1, dev_2_Enabled:1, dev_3_Enabled:1, dev_4_Enabled:1, :4; };    
	tOSData  mutex, event;
} tSpiPort;

/*Variable Definition*/
extern tSpiPort spiPort0;
extern tSpiPort spiPort1;

/* SSD1306 SPI functions */
eSpiInitError SSD1306_SPI_Initialize(eCSDevice device);
void SSD1306_SPI_Close(eCSDevice device);
unsigned portCHAR SSD1306_SPI_ReadWrite(pSpiRWdata pData);
void SPI_SendCommand(unsigned portCHAR cmd);
void SPI_SendData(unsigned portCHAR* pData, size_t size);
extern void vSpiISREntry0( void ); /* Interrupt entry point written in the assembler file serialISR.s */

/* SD card SPI functions */
eSpiInitError SD_SPI_Initialize(eCSDevice device);
void SD_SPI_Close(eCSDevice device);
unsigned portCHAR SD_SPI_ReadWrite(pSpiRWdata pData);
extern void vSpiISREntry1( void ); /* Interrupt entry point written in the assembler file serialISR.s */

#endif	//SSD1306_H_